/*
 * Copyright 2021 Hannes Dorfmann.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package com.hannesdorfmann.mosby3.sample.mvi.view.search;

import com.hannesdorfmann.mosby3.mvi.MviFraction;
import com.hannesdorfmann.mosby3.sample.mvi.MyApplication;
import com.hannesdorfmann.mosby3.sample.mvi.ResourceTable;
import com.hannesdorfmann.mosby3.sample.mvi.businesslogic.interactor.search.SearchViewState;
import com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.Product;
import com.hannesdorfmann.mosby3.sample.mvi.view.detail.ProductDetailsAbility;
import com.hannesdorfmann.mosby3.sample.mvi.view.ui.viewholder.ProductViewHolder;
import com.hannesdorfmann.mosby3.sample.mvi.view.widge.CirleProgressImg;
import com.jakewharton.rxbinding2.widget.RxSearchBar;
import io.reactivex.Observable;
import java.util.List;
import java.util.concurrent.TimeUnit;

import ohos.agp.components.*;
import ohos.agp.utils.Color;
import ohos.app.Context;

/**
 * @author Hannes Dorfmann
 */
public class SearchFraction extends MviFraction<SearchView, SearchPresenter>
    implements SearchView, ProductViewHolder.ProductClickedListener {

  SearchBar searchBar;
  StackLayout container;
  CirleProgressImg loadingView;
  Text errorView;
  ListContainer listContainer;
  Text emptyView;
  int spanCount = 2;

  private SearchAdapter adapter;
  Context context;

  public SearchFraction(Context context){
    this.context = context;
  }

  @Override public void onProductClicked(Product product) {
    ProductDetailsAbility.start(getFractionAbility(), product);
  }

  public void closeSearchBar(){
      searchBar.getCloseButton().simulateClick();
  }

  @Override
  protected int getUIContent() {
    return ResourceTable.Layout_fragment_search;
  }

  @Override
  protected void initCompoment() {

    searchBar =  (SearchBar) mComponent.findComponentById(ResourceTable.Id_searchBar);
    container = (StackLayout) mComponent.findComponentById(ResourceTable.Id_container);
    loadingView = (CirleProgressImg) mComponent.findComponentById(ResourceTable.Id_loadingView);
    errorView = (Text) mComponent.findComponentById(ResourceTable.Id_errorView);
    listContainer = (ListContainer) mComponent.findComponentById(ResourceTable.Id_listContainer);
    emptyView = (Text) mComponent.findComponentById(ResourceTable.Id_emptyView);

    adapter = new SearchAdapter(LayoutScatter.getInstance(getFractionAbility()), this);
    listContainer.setItemProvider(adapter);

    searchBar.activateSubmitButton(true);
    searchBar.setSearchButton(ResourceTable.Media_ic_search);
    searchBar.setSearchHint("Search...");
    searchBar.setSearchTextColor(Color.BLACK);
    searchBar.setTextSize(24);
    searchBar.setSearchIcon(ResourceTable.Media_ic_search);
    searchBar.setCloseButton(ResourceTable.Media_ic_clear_search_api_holo_light);
  }

  @Override public SearchPresenter createPresenter() {
    return MyApplication.getDependencyInjection(getFractionAbility()).newSearchPresenter();
  }

  @Override public Observable<String> searchIntent() {
    return RxSearchBar.queryTextChanges(searchBar)
        .skip(2) // Because after screen orientation changes query Text will be resubmitted again
        .filter(queryString -> queryString.length() > 3 || queryString.length() == 0)
        .debounce(500, TimeUnit.MILLISECONDS)
        .distinctUntilChanged()
        .map(CharSequence::toString);
  }

  @Override public void render(SearchViewState viewState) {
    if (viewState instanceof SearchViewState.SearchNotStartedYet) {
      renderSearchNotStarted();
    } else if (viewState instanceof SearchViewState.Loading) {
      renderLoading();
    } else if (viewState instanceof SearchViewState.SearchResult) {
      renderResult(((SearchViewState.SearchResult) viewState).getResult());
    } else if (viewState instanceof SearchViewState.EmptyResult) {
      renderEmptyResult();
    } else if (viewState instanceof SearchViewState.Error) {
      renderError();
    } else {
      throw new IllegalArgumentException("Don't know how to render viewState " + viewState);
    }
  }

  private void renderResult(List<Product> result) {
//    TransitionManager.beginDelayedTransition(container);
    listContainer.setVisibility(Component.VISIBLE);
    loadingView.setVisibility(Component.HIDE);
    emptyView.setVisibility(Component.HIDE);
    errorView.setVisibility(Component.HIDE);
    adapter.setProducts(result);
    adapter.notifyDataChanged();
  }

  private void renderSearchNotStarted() {
    listContainer.setVisibility(Component.HIDE);
    loadingView.setVisibility(Component.HIDE);
    errorView.setVisibility(Component.HIDE);
    emptyView.setVisibility(Component.HIDE);
  }

  private void renderLoading() {
    listContainer.setVisibility(Component.HIDE);
    loadingView.setVisibility(Component.VISIBLE);
    errorView.setVisibility(Component.HIDE);
    emptyView.setVisibility(Component.HIDE);
  }

  private void renderError() {
    listContainer.setVisibility(Component.HIDE);
    loadingView.setVisibility(Component.HIDE);
    errorView.setVisibility(Component.VISIBLE);
    emptyView.setVisibility(Component.HIDE);
  }

  private void renderEmptyResult() {
//    TransitionManager.beginDelayedTransition(container);
    listContainer.setVisibility(Component.HIDE);
    loadingView.setVisibility(Component.HIDE);
    errorView.setVisibility(Component.HIDE);
    emptyView.setVisibility(Component.VISIBLE);
  }

}
